import threading
# from ...utils.types import *
from src.types_pydantic.zlgcan_zuds_types import Uds_ResponseStatus_Type, Uds_Request_Type, Uds_Negative_Data_Type, Uds_Positive_Data_Type, Uds_Response_Type, Uds_ResponseType_Type

# from ...zuds.zuds import Zuds_Tester_Base, GLOBAL_ZUDS_TESTER

import sys
import time
import random
from datetime import datetime
from concurrent.futures import ThreadPoolExecutor
from src.utils.aes_algorithm import seed_to_key_algorithm_list
# from ...utils.loggers import ic_debugger


class Serve_Func:
    def __init__(self, tester, rooter) -> None:
        self.ROOTER = rooter
        # tester 是用来发送和处理数据的
        self.TESTER = tester

        self.UdsHandler_pool = ThreadPoolExecutor(max_workers=1)

        pass

    def response_show(self, funcJobObj, response: Uds_Response_Type):
        show_string = self.response_show_string(response)
        if response.status == Uds_ResponseStatus_Type.ZCAN_UDS_ERROR_OK:
            if response.type == Uds_ResponseType_Type.NEGATIVE:
                funcJobObj.display_recvUds_negative(show_string)
            if response.type == Uds_ResponseType_Type.POSITIVE:
                funcJobObj.display_recvUds_positive(show_string)
        else:
            funcJobObj.display_recvUds_negative(show_string)

    def response_show_string(self, response: Uds_Response_Type):
        timestamp = f'{datetime.now():%Y-%m-%d %H:%M:%S}'
        if response.status == 0:
            status = "success"
            if response.type == 0:
                positive_negative = "消极"
                result_show_string = f'{timestamp},通讯:{status},响应:{positive_negative},sid:{response.response.sid:02x},neg_code:{
                    response.response.neg_code:02x},error_code:{response.response.error_code:02x}'
            if response.type == 1:
                positive_negative = "积极"
                result_show_string = f'{timestamp},通讯:{status},响应:{positive_negative},sid:{response.response.sid:02x},param_len:{
                    response.response.param_len},param:[{' '.join(hex(item) for item in response.response.param)}]'
        else:
            status = "error"
            if response.status == 1:
                error_msg = ("响应超时")
            elif response.status == 2:
                error_msg = ("传输失败，请检查链路层，或请确认流控帧是否回复")
            elif response.status == 3:
                error_msg = ("取消请求")
            elif response.status == 4:
                error_msg = ("抑制响应")
            elif response.status == 5:
                error_msg = ("忙碌中")
            elif response.status == 6:
                error_msg = ("请求参数错误")
            else:
                error_msg = ("其他错误")
            result_show_string = f'{timestamp},通讯:{status},错误信息:{error_msg}'
        return result_show_string

    def response_transform(self, response, uds_request: Uds_Request_Type):
        resp_status = response.status
        if resp_status == 0:
            resp_type = response.type
            if resp_type == Uds_ResponseType_Type.POSITIVE:
                resp_positive_sid = response.response.positive.sid
                resp_positive_param_len = response.response.positive.param_len
                param = response.response.positive.param
                resp_positive_param = [(param[i])
                                       for i in range(resp_positive_param_len)]

                resp_positive = Uds_Positive_Data_Type(
                    sid=resp_positive_sid, param=resp_positive_param, param_len=resp_positive_param_len)

                result_response = Uds_Response_Type(
                    status=resp_status, type=resp_type, response=resp_positive)

            if resp_type == Uds_ResponseType_Type.NEGATIVE:
                resp_negative_code = response.response.negative.neg_code
                resp_negative_sid = response.response.negative.sid
                resp_negative_error_code = response.response.negative.error_code
                resp_negative = Uds_Negative_Data_Type(
                    neg_code=resp_negative_code, sid=resp_negative_sid, error_code=resp_negative_error_code)
                result_response = Uds_Response_Type(
                    status=resp_status, type=resp_type, response=resp_negative)
        # 如果响应状态不为0，那么就是错误
        else:
            result_response = Uds_Response_Type(status=resp_status)
            dst_addr = uds_request.req_dst_addr
            sid = uds_request.req_sid
            req_info = f'[ dst:0x{dst_addr:03x} sid:{sid:02x} ]==>'
            if resp_status == 1:
                # print("响应超时")
                print(f'[file:{__file__}]=>[line:{
                      (sys._getframe().f_lineno)}]==>{req_info}响应超时')
            elif resp_status == 2:
                # print("传输失败，请检查链路层，或请确认流控帧是否回复")
                print(f'[file:{__file__}]=>[line:{(sys._getframe().f_lineno)}]==>{
                      req_info}传输失败，请检查链路层，或请确认流控帧是否回复')
            elif resp_status == 3:
                # print("取消请求")
                print(f'[file:{__file__}]=>[line:{
                      (sys._getframe().f_lineno)}]==>{req_info}取消请求')
            elif resp_status == 4:
                # print("抑制响应")
                print(f'[file:{__file__}]=>[line:{
                      (sys._getframe().f_lineno)}]==>{req_info}抑制响应')
            elif resp_status == 5:
                print(f'[file:{__file__}]=>[line:{
                      (sys._getframe().f_lineno)}]==>{req_info}忙碌中...')
                # print("忙碌中")
            elif resp_status == 6:
                # print("请求参数错误")
                print(f'[file:{__file__}]=>[line:{
                      (sys._getframe().f_lineno)}]==>{req_info}请求参数错误')
        return result_response

    def send_and_handle_uds_msg(self, uds_request: Uds_Request_Type):
        # 显示发送信息
        if self.ROOTER.UDS_DISPLAY:
            self.ROOTER.UDS_DISPLAY.display_sendUds(uds_request)
        else:
            print(f'[file:{__file__}]=>[line:{
                  (sys._getframe().f_lineno)}]==>发送{uds_request}')
        uds_request_dict = uds_request.model_dump()
        # print(f'[file:{__file__}]=>[line:{(sys._getframe().f_lineno)}]==>发送{
        #       uds_request_dict}')

        try_counts = 3
        while try_counts > 0:
            raw_response = self.TESTER.handle_uds_msg(
                **uds_request_dict)
            # [ ] 会不会在这里就返回None，需要进一步确认
            # ic_debugger(raw_response)
            # 此处添加请求信息进去，跟踪出现错误的是哪个请求request
            response: Uds_Response_Type = self.response_transform(
                raw_response, uds_request=uds_request)

            # 显示返回响应
            if self.ROOTER.UDS_DISPLAY:
                self.response_show(self.ROOTER.UDS_DISPLAY, response)
            else:
                print(f'[file:{__file__}]=>[line:{
                      (sys._getframe().f_lineno)}]==>响应{response}')
            # [ ]: 没有错误就算成功，还是必须正响应才算成功,需要进一步确认
            if response.status == Uds_ResponseStatus_Type.ZCAN_UDS_ERROR_OK:
                return response
            else:
                try_counts -= 1
                print(f'[file:{__file__}]=>[line:{
                    (sys._getframe().f_lineno)}]==>发送{uds_request_dict}未收到成功响应，剩余次数{try_counts}')
                # [ ] 这里一旦加上延时，测试时错误概率就很高，原因未知
                # time.sleep(0.01)
        return response

    def serve_default(self, uds_request):

        return self.send_and_handle_uds_msg(uds_request)

    def serve_10(self, option_func=0x03,  srcAddr=0x737, dstAddr=0x7b7):
        uds_request = Uds_Request_Type(
            req_src_addr=srcAddr, req_dst_addr=dstAddr, req_sid=0x10, req_param_len=0x1, req_data_1=[option_func])

        return self.send_and_handle_uds_msg(uds_request)

    def serve_10_01(self, srcAddr=0x737, dstAddr=0x7b7):
        return self.serve_10(option_func=0x01, srcAddr=srcAddr, dstAddr=dstAddr)

    def serve_10_03(self, srcAddr=0x737, dstAddr=0x7b7):
        return self.serve_10(option_func=0x03, srcAddr=srcAddr, dstAddr=dstAddr)

    def serve_28(self, option_func=0x03, srcAddr=0x737, dstAddr=0x7b7):
        uds_request = Uds_Request_Type(
            req_src_addr=srcAddr, req_dst_addr=dstAddr, req_sid=0x28, req_param_len=0x1, req_data_1=[option_func])

        return self.send_and_handle_uds_msg(uds_request)

    def serve_28_03(self, srcAddr=0x737, dstAddr=0x7b7):
        return self.serve_28(option_func=0x03, srcAddr=srcAddr, dstAddr=dstAddr)

    def serve_22(self, did1, did2, srcAddr=0x737, dstAddr=0x7b7, *args, **kwargs):
        uds_request = Uds_Request_Type(
            req_src_addr=srcAddr, req_dst_addr=dstAddr, req_sid=0x22, req_param_len=0x2, req_data_1=[did1, did2])

        return self.send_and_handle_uds_msg(uds_request)

    def serve_22_f190(self, srcAddr=0x737, dstAddr=0x7b7, did1=0xf1, did2=0x90):
        return self.serve_22(srcAddr=srcAddr, dstAddr=dstAddr, did1=did1, did2=did2)

    def sever_2e_param(self, srcAddr=0x737, dstAddr=0x7b7, params=None):
        # 默认2e写入随机VIN
        if params is None:
            params = [0xf1, 0x90] + [(random.randint(0x41, 0x5a))
                                     for i in range(17)]
        uds_request = Uds_Request_Type(
            req_src_addr=srcAddr, req_dst_addr=dstAddr, req_sid=0x2e, req_param_len=len(params), req_data_1=params)

        return self.send_and_handle_uds_msg(uds_request)

    def serve_3e_once(self, srcAddr=0x737, dstAddr=0x7b7, *args, **kwargs):
        uds_request = Uds_Request_Type(
            req_src_addr=srcAddr, req_dst_addr=dstAddr, req_sid=0x3e, req_param_len=0x1, req_data_1=[0x00])

        return self.send_and_handle_uds_msg(uds_request)

    def serve_27_01_02(self, srcAddr=0x737, dstAddr=0x7b7, Learmask="5f0f50a1", algo="algo1"):

        # DOC: 27 01 发送
        uds_request = Uds_Request_Type(
            req_src_addr=srcAddr, req_dst_addr=dstAddr, req_sid=0x27, req_param_len=0x1, req_data_1=[0x01])

        uds_request_dict = uds_request.model_dump()
        raw_response = self.TESTER.handle_uds_msg(
            **uds_request_dict)
        response: Uds_Response_Type = self.response_transform(
            raw_response, uds_request=uds_request)
        if self.ROOTER.UDS_DISPLAY:
            self.response_show(self.ROOTER.UDS_DISPLAY, response)

        # DOC: 27 01 接收的数据，生成秘钥
        if response.status == Uds_ResponseStatus_Type.ZCAN_UDS_ERROR_OK and response.type == Uds_ResponseType_Type.POSITIVE:
            positive_data = response.response.param
            # 如果已经解锁，那么反馈的positive_data是[1,0,0,0,0]
            print(f'[file:{__file__}]=>[line:{
                (sys._getframe().f_lineno)}]==> 27 01: positive_data:{[hex(item) for item in positive_data]}')

            # return True
            time.sleep(0.1)
            # 根据algo配置，选择合适的解密算法
            algorithm = seed_to_key_algorithm_list[algo]
            key = algorithm(positive_data, Learmask=Learmask)
            # if Qbaic:
            #     key = seed_to_key_Qbaic(positive_data, Learmask=Learmask)
            # else:
            #     key = seed_to_key(positive_data, Learmask=Learmask)
            # print('key:', key)  # 生成秘钥
            # ic_debugger(key)

            # DOC 把02子功能，加到req_data_1中

            req_data_1 = [0x02, *key]

            req_param_len = len(req_data_1)
            uds_request = Uds_Request_Type(
                req_src_addr=srcAddr, req_dst_addr=dstAddr, req_sid=0x27, req_param_len=req_param_len, req_data_1=req_data_1)
            if self.ROOTER.UDS_DISPLAY:
                self.ROOTER.UDS_DISPLAY.display_sendUds(uds_request)
            uds_request_dict = uds_request.model_dump()
            # ic_debugger(uds_request_dict)
            raw_response = self.TESTER.handle_uds_msg(
                **uds_request_dict)
            response: Uds_Response_Type = self.response_transform(
                raw_response, uds_request=uds_request)
            if self.ROOTER.UDS_DISPLAY:
                self.response_show(self.ROOTER.UDS_DISPLAY, response)
            return response
        else:
            return response

    def serve_2f(self, did1, did2, option_func, data=[], srcAddr=0x737, dstAddr=0x7b7, **kwargs):
        # FIXME:
        param_data = [did1, did2, option_func, *data]
        uds_request = Uds_Request_Type(
            req_src_addr=srcAddr, req_dst_addr=dstAddr, req_sid=0x2f, req_param_len=len(param_data), req_data_1=param_data)

        return self.send_and_handle_uds_msg(uds_request)

    def serve_2f_58a003(self, data=[], srcAddr=0x737, dstAddr=0x7b7):
        return self.serve_2f(0x58, 0xa0, 0x03, data=data,
                             srcAddr=srcAddr, dstAddr=dstAddr)

    def serve_31(self, sub_func=0x01, routineIdentifier=0xf010, routineControlOptionRecord=0x02, srcAddr=0x716, dstAddr=0x796, **kwargs):
        '''
            待完善和验证功能
        '''
        req_sid = 0x31
        _sub_func = sub_func
        routineIdentifier = routineIdentifier
        # 整除0x100，得到商是前两位
        routineIdentifier1 = routineIdentifier // 0x100
        # 取模0x100，得到余数是后两位
        routineIdentifier2 = routineIdentifier % 0x100

        # [ ]: 0x0101 是表示最后一位bit0，实际截图bcan是bit1，待确认
        # [ ]: param的构造是否正常？
        routineControlOptionRecord = routineControlOptionRecord
        param_data = [_sub_func, routineIdentifier1,
                      routineIdentifier2, routineControlOptionRecord]

        uds_request = Uds_Request_Type(
            req_src_addr=srcAddr, req_dst_addr=dstAddr, req_sid=req_sid, req_param_len=len(param_data), req_data_1=param_data)

        return self.send_and_handle_uds_msg(uds_request=uds_request)


# [ ]: tkinter 自带的定时器，是否可以替换？ after方法
class Cycle_Runner:
    def __init__(self, func, cycle_time=3, *arg, **kwargs) -> None:
        self._func = func
        self._cycle_time = cycle_time
        self._arg = arg
        self._kwargs = kwargs

        # 线程对象
        self._thread = None
        self._terminate = False

        pass

    def start(self):
        self._thread = threading.Thread(target=self._run)
        self._thread.start()
        pass

    def stop(self):
        self._terminate = True
        pass

    def _run(self):
        while not self._terminate:
            self._func(*self._arg, **self._kwargs)
            time.sleep(self._cycle_time)
            pass


# GLOBAL_UDS_SERVE_FUNC_LIB = Serve_Func()


# def serve_test():
    # serveFunc = Serve_Func(Zuds_Tester_Base())

    # serveFunc.serve_22(did1=0xf1, did2=0x90)
